package com.hw.protocol.tool.controller.transform;

import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONUtil;
import com.hw.protocol.tool.config.ObjIdEnum;
import com.hw.protocol.tool.config.ZbProtocolEnum;
import com.hw.protocol.tool.model.entity.JkProtocol;
import com.hw.protocol.tool.model.entity.jk.BusinessData;
import com.hw.protocol.tool.model.entity.jk.obj.BusinessObj;
import com.hw.protocol.tool.model.entity.jk.obj.FlowReading;
import com.hw.protocol.tool.util.CrcUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author : lihy
 * @date : 2024/3/15 14:29
 * description:
 */
@Slf4j
public class JkTransform extends AbsTransform{
    public static String transform(Object data) {
        JkProtocol protocol = (JkProtocol)data;

        ByteBuf buf = Unpooled.wrappedBuffer(protocol.getData());

        BusinessData businessData = new BusinessData();

        businessData.setFrameSeq(buf.readShort());

        //数据域长度
        businessData.setDataLength(buf.readShort());
        //控制域
        businessData.setCmd(buf.readByte());
        //请求序号
        businessData.setReqSeq(buf.readShort());
        //对象个数
        businessData.setObjCount(buf.readByte());

        //对象
        List<BusinessObj> objList = Optional.ofNullable(businessData.getObjs())
                .orElse(new LinkedList<>());
        if (businessData.getCmd() == (byte) ZbProtocolEnum.ANSWER_READ.getCmd()
                || businessData.getCmd() == (byte) ZbProtocolEnum.ANSWER_WRITE.getCmd()) {
            int objId = buf.readShort() & 0xFFFF;
            int objLength = businessData.getDataLength() - 3;
            byte[] objData = new byte[objLength];
            buf.readBytes(objData);
            objList.add(new BusinessObj(Integer.toHexString(objId & 0xFFFF), objLength, objData));
        } else {
            for (int i = 0; i < (businessData.getObjCount() & 0xFF); i++) {
                int objId = buf.readShort() & 0xFFFF;
                int objLength = buf.readByte() & 0xFF;
                switch (ObjIdEnum.getObjId(objId)) {
                    case H2110:
                        objList.add(new BusinessObj("2110", objLength, buf.readLong()));
                        break;
                    case H2111:
                        objList.add(new BusinessObj("2111", objLength, buf.readLong()));
                        break;
                    case H8A00:
                        objList.add(new BusinessObj("8A00", objLength, getReading(buf)));
                        break;
                   /* case H8A03:
                        objList.add(new BusinessObj("8A03", objLength, getBalance(buf)));
                        break;*/
                    case H8A05:
                    case H8A06:
                    case H8A07:
                    case H8A08:
                    case H8A09:
                    case H8A0A:
                        objList.add(new BusinessObj(Integer.toHexString(objId), objLength, getHisReading(buf)));
                        break;

                    default:
                        log.debug("对象Id：[{}]", objId & 0xFFFF);
                        log.debug("对象长度：[{}]", objLength);
                        byte[] objData = new byte[objLength];
                        buf.readBytes(objData);
                        log.debug("数据：[{}]", CrcUtil.bytesToHex(objData, true));
                        String objCode = Integer.toHexString(objId & 0xFFFF);
                        objList.add(new BusinessObj(objCode, objLength, objData));
                }
            }
        }
        businessData.setObjs(objList);




        return JSONUtil.toJsonStr(businessData).replace(",", ",\n");
    }

    private static final String MAX_LONG = "7FFFFFFFFFFFFFFF";
    private static final String MAX_INT = "7FFFFFFF";
    private static final String MAX_SHORT = "7FFF";
    /**
     * 获取流量计读数
     *
     * @param buf 数据域
     * @return 流量计读数
     */
    private static FlowReading getReading(ByteBuf buf) {
        FlowReading reading = new FlowReading();
        byte[] timeBytes = new byte[6];
        buf.readBytes(timeBytes);
        if (!Arrays.equals(timeBytes, new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF})) {
            reading.setReadTime(DateTime.of(CrcUtil.bytesToHex(timeBytes), "yyMMddHHmmss"));
        }
        long devVolume = buf.readInt();
        reading.setDevVolume(devVolume * 0.01);
        reading.setVolume(devVolume * 0.01);
        long volume = buf.readLong();
        if (volume < Long.parseLong(MAX_LONG, 16)) {
            reading.setVolume(volume * 0.001);
        }
        long realVolume = buf.readLong();
        if (volume < Long.parseLong(MAX_LONG, 16)) {
            reading.setRealVolume(realVolume * 0.001);
        }
        long flux = buf.readInt();
        if (flux < Integer.parseInt(MAX_INT, 16)) {
            reading.setFlux(flux * 0.001);
        }
        long realFlux = buf.readInt();
        if (realFlux < Integer.parseInt(MAX_INT, 16)) {
            reading.setRealFlux(realFlux * 0.001);
        }
        int temperature = buf.readShort();
        if (temperature < Integer.parseInt(MAX_SHORT, 16)) {
            reading.setTemperature(temperature * 0.01);
        }
        long press = buf.readInt();
        if (press < Integer.parseInt(MAX_INT, 16)) {
            reading.setPress(press);
        }
        reading.setMeterStatus(buf.readByte());
        reading.setBatteryStatus(buf.readByte());
        return reading;
    }

    private static List<FlowReading> getHisReading(ByteBuf buf) {
        List<FlowReading> list = new LinkedList<>();
        for (int i = 0; i < 5; i++) {
            FlowReading reading = new FlowReading();
            byte[] timeBytes = new byte[6];
            buf.readBytes(timeBytes);
            try {
                reading.setReadTime(DateTime.of(CrcUtil.bytesToHex(timeBytes), "yyMMddHHmmss"));
            } catch (Exception e) {
                log.warn("时间格式错误，{}", e.getMessage());
            }
            //脉冲模式获取数据
            long devVolume = buf.readInt();
            reading.setDevVolume(devVolume * 0.01);
            reading.setVolume(devVolume * 0.01);
            /*
            //总线模式获取数据
            long volume = buf.readInt();
            if (volume < Long.parseLong(MAX_INT, 16)) {
                reading.setVolume(volume * 0.01);
            }
            long realVolume = buf.readInt();
            if (volume < Long.parseLong(MAX_INT, 16)) {
                reading.setRealVolume(realVolume * 0.01);
            }
            int temperature = buf.readShort();
            if (temperature < Integer.parseInt(MAX_SHORT, 16)) {
                reading.setTemperature(temperature * 0.01);
            }
            long press = buf.readInt();
            if (press < Integer.parseInt(MAX_INT, 16)) {
                reading.setPress(press);
            }*/
            //跳过总线数据
            buf.skipBytes(14);
            log.debug("历史数据：[{}]", reading.toString());
            list.add(reading);
            //跳过状态、金额数据
            buf.skipBytes(21);
        }
        return list.stream().filter(fr -> null != fr.getReadTime()).collect(Collectors.toList());
    }

}
